Java算法中的栈
Deque(双端队列)在 Java 中,它同时承担了 C++ 中 std::stack 和 std::queue 的角色。
不要使用java中的Stack 类(它是旧 vector 实现的,同步且慢),使用 Deque 接口的实现类 ArrayDeque。
以下是 Deque 的核心 API 整理,按使用场景分类:
1. 初始化
// 必须引入包
import java.util.Deque;
import java.util.ArrayDeque;
import java.util.LinkedList;
// 写法 1:最常用(基于数组,性能好,类似 C++ vector)
Deque<Integer> stack = new ArrayDeque<>();
// 写法 2:基于链表(如果需要频繁在中间插入删除,或者作为链表使用)
Deque<Integer> queue = new LinkedList<>();
2. 当作 栈 (Stack) 使用 (LIFO)
对应 C++ 的 std::stack。
操作都在头部(Head)进行。
| 操作 | 方法名 | 描述 | 遇到空时的行为 |
|---|---|---|---|
| 入栈 | push(E e) | 添加元素到栈顶 | 抛异常 (如果容量满) |
| 出栈 | pop() | 移除并返回栈顶元素 | 抛异常 (NoSuchElementException) |
| 查看 | peek() | 返回栈顶元素但不移除 | 返回 null |
注意:Java 的 pop() 会抛异常,所以通常先判断 isEmpty()。或者使用 poll() (返回 null),但在 Stack 语义下大家习惯用 pop()。
3. 当作 队列 (Queue) 使用 (FIFO)
对应 C++ 的 std::queue。
队尾(Tail)进,队头(Head)出。
| 操作 | 方法名 | 描述 | 遇到空时的行为 |
|---|---|---|---|
| 入队 | offer(E e) | 添加元素到队尾 | 返回 false (比 add 安全) |
| 出队 | poll() | 移除并返回队头元素 | 返回 null (比 remove 安全) |
| 查看 | peek() | 返回队头元素但不移除 | 返回 null |
4. 当作 双端队列 (Deque) 使用
对应 C++ 的 std::deque。如果你需要两头操作(比如滑窗最大值问题),用这些明确的方法:
| 方向 | 插入 (Insert) | 移除 (Delete) | 查看 (Examine) |
|---|---|---|---|
| 头部 (First) | offerFirst(e) / addFirst(e) | pollFirst() / removeFirst() | peekFirst() / getFirst() |
| 尾部 (Last) | offerLast(e) / addLast(e) | pollLast() / removeLast() | peekLast() / getLast() |
记忆技巧:
- offer/poll/peek 是不抛异常的版本(返回 false/null)。
- add/remove/get 是抛异常的版本。
- 刷题时建议用 offer/poll/peek 防止 Crash。
5. 常用通用方法
Deque<Integer> dq = new ArrayDeque<>();
dq.isEmpty(); // 判空,相当于 C++ empty()
dq.size(); // 大小,相当于 C++ size()
dq.contains(x); // 是否包含,O(N) 复杂度
dq.clear(); // 清空
6. 遍历与输出
ArrayDeque 的迭代器是从 Head (栈顶/队头) 到 Tail (栈底/队尾) 的。
假设按顺序 Push 了:1, 2, 3。
栈结构是:[3, 2, 1] (3 是栈顶)。
方式 A:普通的 for-each (从头到尾)
// 栈顶 -> 栈底
for (Integer i : stack) {
System.out.print(i);
}
// 输出: 321
方式 B:转为 String 输出 (正序需求)
如果你想恢复成存入的顺序 123,有三种办法:
-
从尾部取 (推荐):
while (!stack.isEmpty()) { System.out.print(stack.pollLast()); // 移除并打印栈底元素 } -
逆序迭代器:
Iterator<Integer> it = stack.descendingIterator(); while(it.hasNext()) { System.out.print(it.next()); } -
转 List 再反转 (慢,不推荐):
List<Integer> list = new ArrayList<>(stack); Collections.reverse(list);
总结速查
| 场景 | 核心 API |
|---|---|
| 模拟 Stack | push(), pop(), peek() |
| 模拟 Queue | offer(), poll(), peek() |
| 两头都要动 | offerFirst/Last, pollFirst/Last |
| 避坑 | ArrayDeque 不允许存 null,存 null 会报错。 |
💬 评论